#region Imported Namespace
using System;
using System.Data;
using System.Text;
using System.Data.SqlClient;
using UserContext = PHSRAG.Insight21.Context.UserContext;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
#endregion

namespace PHSRAG.Insight21.Purchasing
{
	/// <summary>
	/// This class is a factory class for the user order object model.
	/// It includes static methods to create, restore, and bulk delete
	/// user orders. It also holds an enumeration listing all the user
	/// order types.
	/// </summary>
	public class UserOrderUtility
	{
		#region Constants
		
		private const string DeleteUserOrdersSPName			= "DeleteUserOrders";
		private const string DeleteReconcileOrdersSPName	= "DeleteReconcileOrders";
		
		// SP parameter names for deleting user order
		private const string OrderIDListParamName			= "@idsToDelete";
		private const string DomainUserIDParamName			= "@domainUserID";		
		
		#endregion
		
		#region Enumeration
		/// <summary>
		/// Enumeartes the various user order types
		/// </summary>
		public enum UserOrderType 
		{
			PurchaseOrder		=	1,
			TravelVoucher		=	2,
			ChequeRequest		=	3,
			JournalEntry		=	4,
			PettyCash			=	5
		}		
		#endregion		
		
		#region Create New User Order

		/// <summary>
		/// Instantiates and returns a user order object using the specified order type.
		/// </summary>
		/// <param name="orderType">user order type</param>
		/// <param name="cachePolicy">cache policy for the user order to be created</param>
		/// <returns>user order of the type specified</returns>
		public static UserOrder CreateUserOrder(UserOrderType orderType, ICachePolicy cachePolicy)
		{
			switch(orderType)
			{				
				case UserOrderType.PurchaseOrder:
					return new PurchaseOrder(cachePolicy);

				case UserOrderType.JournalEntry:
					return new JournalEntry(cachePolicy);

				case UserOrderType.PettyCash:
					return new JournalEntry(cachePolicy);

				case UserOrderType.TravelVoucher:
					return new Voucher(cachePolicy);

				case UserOrderType.ChequeRequest:
					return new Voucher(cachePolicy);

				default:
					throw new Exception(@"Invalid Order Type Requested");
			}			
		}
		#endregion

		#region Load User Order
		/// <summary>
		/// Creates and loads the UserOrder object from the database given the order id.
		/// This method gets the order type of the given order id, and calls the overload
		/// for LoadUserOrder to get a loaded user order object and returns it to the calling
		/// routine
		/// </summary>
		/// <param name="orderId">order id of the user order</param>
		/// <param name="cachePolicy">Specifed Cache policy</param>		
		/// <returns>User order object with its data loaded for the given order id</returns>
		public static UserOrder LoadUserOrder(int orderID, ICachePolicy cachePolicy)
		{
			return UserOrderUtility.LoadUserOrder(orderID, UserOrderHelper.GetOrderType(orderID), cachePolicy);		
		}

		/// <summary>
		/// Creates and loads the UserOrder object from the database given the order id and order type.
		/// This method instantiate the appropriate user order object using the specified order type,
		/// loads the object with data using the order id and returns the user order object.
		/// </summary>
		/// <param name="orderId">order id of the user order</param>
		/// <param name="cachePolicy">Specifed Cache policy</param>		
		/// <returns>User order object with its data loaded for the given order id</returns>
		public static UserOrder LoadUserOrder(int orderID, UserOrderType orderType, ICachePolicy cachePolicy)
		{
			try
			{
				UserOrder userOrder = UserOrderUtility.CreateUserOrder(orderType, cachePolicy);

				userOrder.Load(Utility.DataAccess.GetConnectionString(),
					((UserContext)cachePolicy.GetCachedObject(UserContext.CacheKey)).DomainUserId, 
					orderID, orderType);

				return userOrder;
			}
			catch(Exception ex)
			{
				throw(new Exception("Error in loading user order", ex));
			}
		} 

		#endregion

		#region Convert User Order
		
		/// <summary>
		/// This method converts the type of user order to the type requested and
		/// returns it after populating its values from the database if the OrderId 
		/// is more than zero or creating a new user order object of the desired type.
		/// It then assigns the common values from the exisiting user order object to 
		/// the converted user order.
		/// </summary>
		/// <param name="userOrder">existing order type</param>
		/// <param name="orderType">new user order type desired</param>
		/// <param name="cachePolicy">cache policy for the user order object to be created</param>
		/// <returns>User order object with its data loaded for the given order id</returns>
		public static UserOrder ConvertUserOrder(UserOrder userOrder, 
			UserOrderType orderType, ICachePolicy cachePolicy)
		{
			UserOrder convertedUserOrder;

			if(userOrder.OrderID > 0)
			{
				convertedUserOrder = UserOrderUtility.LoadUserOrder(userOrder.OrderID, orderType, cachePolicy);
				
				//when no rows exist for given order id
				if(convertedUserOrder.GetDataContainer().Tables[Constants.UserOrderDetailsHeaderTableName].
					Rows.Count.Equals(0))
				{
					convertedUserOrder.CreateHeaderTableAndAddRow();
					// accept change is done so that converted user order is updated to the database.
					convertedUserOrder.GetDataContainer().Tables[Constants.UserOrderDetailsHeaderTableName].
						AcceptChanges();
				}
			}
			else
			{
				convertedUserOrder = UserOrderUtility.CreateUserOrder(orderType, cachePolicy);
				convertedUserOrder.CreateHeaderTableAndAddRow();
			}
			convertedUserOrder.AssignProperties(userOrder, orderType);
			return convertedUserOrder;
		}
		#endregion

		#region Bulk Delete User Orders
		/// <summary>
		/// This method is used to bulk delete user orders from the insight data tables
		/// and the reconcile store. It receives a comma separated list of order ids and an
		/// cache policy object. It creates a connection and transaction object using the specified
		/// connection string and deletes the user orders from the reconcile store and insight
		/// tables using the transaction object.
		/// </summary>
		/// <param name="orderIDList">string containing list of order ids</param>
		/// <param name="cachePolicy">prevalent cache policy</param>
		public static void DeleteUserOrders(string orderIDList, ICachePolicy cachePolicy)
		{
			SqlConnection connection = new SqlConnection(Utility.DataAccess.ConnectionString);			
			SqlTransaction transaction = null;
			try 
			{
				int domainUserID = ((UserContext)cachePolicy.GetCachedObject(UserContext.CacheKey)).DomainUserId;
				
				connection.Open();
				transaction = connection.BeginTransaction();
				
				Utility.DataAccess.ExecuteNonQuery(connection, transaction, DeleteReconcileOrdersSPName, 
					Utility.DataAccess.BuildSqlParameterArray(
					OrderIDListParamName, SqlDbType.VarChar, orderIDList,
					DomainUserIDParamName, SqlDbType.Int, domainUserID));
				
				Utility.DataAccess.ExecuteNonQuery(connection, transaction, DeleteUserOrdersSPName, 
					Utility.DataAccess.BuildSqlParameterArray(
					OrderIDListParamName, SqlDbType.VarChar, orderIDList,
					DomainUserIDParamName, SqlDbType.Int, domainUserID));

				transaction.Commit();
				UserOrderHelper.UnCacheDependentReports(cachePolicy);
			} 
			catch (Exception ex) 
			{
				if(transaction != null)
                    transaction.Rollback();
				throw(new Exception(@"Error in deleting user orders.", ex));
			} 
			finally 
			{
				if (connection.State != ConnectionState.Closed)
					connection.Close();
			}			
		}
		#endregion		
	}
}
